package com.rf.richfitwheel.admin.basedata.service.impl;

import com.rf.richfitwheel.admin.basedata.dao.BasicDataOrgTreeMapper;
import com.rf.richfitwheel.admin.basedata.model.BasicDataOrgTree;
import com.rf.richfitwheel.admin.basedata.model.BasicDataOrgTreeEntity;
import com.rf.richfitwheel.admin.basedata.model.BasicDataOrgTreeExample;
import com.rf.richfitwheel.admin.basedata.service.BasicDataOrgService;
import com.rf.richfitwheel.admin.conf.BasicDataPropertiesConfig;
import com.rf.richfitwheel.admin.contants.UrlConstant;
import com.rf.richfitwheel.admin.iam.HttpEntityJsonUtil;
import com.rf.richfitwheel.admin.sys.model.Org;
import com.rf.richfitwheel.admin.sys.service.OrgService;
import com.rf.richfitwheel.admin.sys.vo.UserVO;
import com.rf.richfitwheel.common.contants.Constant;
import com.rf.richfitwheel.common.exception.BusinessException;
import com.rf.richfitwheel.common.utils.DateUtils;
import com.rf.richfitwheel.common.utils.StringUtils;
import com.rf.richfitwheel.common.utils.UuidUtil;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BasicDataOrgServiceImpl implements BasicDataOrgService {

    private final Logger log = LoggerFactory.getLogger(BasicDataOrgServiceImpl.class);

    @Autowired
    private BasicDataPropertiesConfig baseDataPropertiesConfig;
    @Autowired
    private BasicDataOrgTreeMapper basicDataOrgTreeMapper;
    @Autowired
    private OrgService orgService;
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;
    /**
     * 从主数据平台同步组织机构数据并入库
     *
     * @param myDate   时间戳毫秒值，同步的时间
     * @param countSyn 记录数
     * @return 记录数
     */
    @Override
    public Integer orgSynDo(long myDate, Integer countSyn) throws URISyntaxException, IOException {
        //请求头
        String randomStr = getRandomStr();
        long timestamp = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Header[] headers = {
                new BasicHeader("appKey", baseDataPropertiesConfig.getAppKey()),
                new BasicHeader("nonce", randomStr),
                new BasicHeader("timestamp", String.valueOf(timestamp)),
                new BasicHeader("signature", sha1Encrypt(MessageFormat.format("{0}{1}{2}{3}",
                        baseDataPropertiesConfig.getAppKey(), baseDataPropertiesConfig.getAppSecret(),
                        String.valueOf(timestamp), randomStr)))
        };
        HttpGet httpGet = new HttpGet(baseDataPropertiesConfig.getUrl() + UrlConstant.BASIC_DATA_ORG_SYNC
            + "?offset=0&limit=10000");
        // 请求头中设置授权TOKEN
        httpGet.setHeaders(headers);
        CloseableHttpResponse response = HttpEntityJsonUtil.getHttpsClient(
                baseDataPropertiesConfig.getUrl().contains("https")).execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();
        HttpEntity entity = response.getEntity();
        if(statusCode == org.apache.http.HttpStatus.SC_OK){
            BasicDataOrgTreeEntity orgTreeEntity = HttpEntityJsonUtil.httpEntityContentToJsonArray(entity, BasicDataOrgTreeEntity.class);
            if(orgTreeEntity == null){
                log.error("调用门户同步机构数据失败：{}", EntityUtils.toString(entity));
            }else{
//                log.info("调用门户同步机构数据临时打印：{}", orgTreeEntity.getItems().get(0));
                List<BasicDataOrgTree> list = orgTreeEntity.getItems().stream().map(m -> {
                    BasicDataOrgTree orgTree = new BasicDataOrgTree();
                    orgTree.setObjectId(StringUtils.isBlank(m.get("OBJECT_ID")) ? null : m.get("OBJECT_ID").toString());
                    orgTree.setVersionNumber(StringUtils.isBlank(m.get("VERSION_NUMBER")) ? null : ((Double) m.get("VERSION_NUMBER")).intValue());
                    orgTree.setTenantId(StringUtils.isBlank(m.get("TENANT_ID")) ? null : m.get("TENANT_ID").toString());
                    orgTree.setCreateBy(StringUtils.isBlank(m.get("CREATE_BY")) ? null : m.get("CREATE_BY").toString());
                    orgTree.setCreateDate(StringUtils.isBlank(m.get("CREATE_DATE")) ? null : DateUtils.stringToDate(m.get("CREATE_DATE").toString(), DateUtils.DATE_TIME_PATTERN));
                    orgTree.setUpdateBy(StringUtils.isBlank(m.get("UPDATE_BY")) ? null : m.get("UPDATE_BY").toString());
                    orgTree.setUpdateDate(StringUtils.isBlank(m.get("UPDATE_DATE")) ? null : DateUtils.stringToDate(m.get("UPDATE_DATE").toString(), DateUtils.DATE_TIME_PATTERN));
                    orgTree.setUpdateLogin(StringUtils.isBlank(m.get("UPDATE_LOGIN")) ? null : m.get("UPDATE_LOGIN").toString());
                    orgTree.setpDeleted(StringUtils.isBlank(m.get("P_DELETED")) ? null : m.get("P_DELETED").toString());
                    orgTree.setId(StringUtils.isBlank(m.get("ID")) ? null : m.get("ID").toString());
                    orgTree.setOrgType((String) (StringUtils.isBlank(m.get("ORGTYPE")) ? m.get("ORG_TYPE") : m.get("ORGTYPE")));
                    orgTree.setOrgName((String) (StringUtils.isBlank(m.get("ORGNAME")) ? m.get("ORG_NAME") : m.get("ORGNAME")));
                    orgTree.setParentId((String) (StringUtils.isBlank(m.get("PARENTID")) ? m.get("PARENT_ID") : m.get("PARENTID")));
                    orgTree.setShortName((String) (StringUtils.isBlank(m.get("SHORTNAME")) ? m.get("SHORT_NAME") : m.get("SHORTNAME")));
                    orgTree.setSocialCreditCode((String) (StringUtils.isBlank(m.get("SOCIALCREDITCODE")) ? m.get("SOCIAL_CREDIT_CODE") : m.get("SOCIALCREDITCODE")));
                    orgTree.setParentSocialCreditCode((String) (StringUtils.isBlank(m.get("PARENTSOCIALCREDITCODE")) ? m.get("PARENT_SOCIAL_CREDIT_CODE") : m.get("PARENTSOCIALCREDITCODE")));
                    orgTree.setOrgLevel((String) (StringUtils.isBlank(m.get("ORGLEVEL")) ? m.get("ORG_LEVEL") : m.get("ORGLEVEL")));
                    orgTree.setAbroadDomestic((String) (StringUtils.isBlank(m.get("ABROADDOMESTIC")) ? m.get("ABROAD_DOMESTIC") : m.get("ABROADDOMESTIC")));
                    orgTree.setCustomerCode((String) (StringUtils.isBlank(m.get("CUSTOMERCODE")) ? m.get("CUSTOMER_CODE") : m.get("CUSTOMERCODE")));
                    orgTree.setDirectlyOrgName((String) (StringUtils.isBlank(m.get("DIRECTLYORGNAME")) ? m.get("DIRECTLY_ORG_NAME") : m.get("DIRECTLYORGNAME")));
                    orgTree.setCountry((String) (StringUtils.isBlank(m.get("COUNTRY")) ? m.get("country") : m.get("COUNTRY")));
                    orgTree.setCity((String) (StringUtils.isBlank(m.get("CITY")) ? m.get("city") : m.get("CITY")));
                    return orgTree;
                }).collect(Collectors.toList());
                if (!list.isEmpty()) {
                    SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
                    BasicDataOrgTreeMapper tempMapper = session.getMapper(BasicDataOrgTreeMapper.class);
                    for(BasicDataOrgTree org : list) {
                        org.setMyId(UuidUtil.get32UUID());
                        org.setMyTime(myDate);
                        org.setMyTimeMat(new Date(myDate));
                        tempMapper.insert(org);
                    }
                    session.commit();
                    countSyn = countSyn + list.size();
                    log.info("已同步{}条组织机构数据", countSyn);
                }else{
                    log.info("已同步0条组织机构数据");
                }
            }
        }else{
            log.error("调用门户同步机构数据失败：{}", EntityUtils.toString(entity));
        }
        EntityUtils.consumeQuietly(entity);
        response.close();
        return countSyn;
    }

    /**
     * 组织机构同步任务，已入库的情况下进行处理
     *
     * @param myDate 时间戳毫秒值，同步的时间
     */
    @Override
    public void orgDeal(long myDate) {
        BasicDataOrgTreeExample example = new BasicDataOrgTreeExample();
        BasicDataOrgTreeExample.Criteria criteria = example.createCriteria();
        //根据入库时间处理数据
        criteria.andMyTimeEqualTo(myDate);
        List<BasicDataOrgTree> list = basicDataOrgTreeMapper.selectByExample(example);
        UserVO user = new UserVO();
        user.setId(Constant.SUPER_ADMIN);
        int count = 0;
        List<Org> listAdd = basicDataOrgTreeMapper.selectForAdd(myDate).stream().map(orgTree -> {
            Org org = new Org();
            //新增
            org.setId(orgTree.getId());
            org.setVersion(0);
            org.setOrgCode(orgTree.getSocialCreditCode());
            org.setOrgName(orgTree.getOrgName());
            org.setShortName(orgTree.getShortName());
            org.setTenantId(Constant.SUPER_ADMIN_TENANTID);
            int level = 0;
            try {
                level = Integer.parseInt(orgTree.getOrgLevel().replace("L", ""));
            } catch (NumberFormatException e) {
                log.error("机构级别转换错误" + orgTree, e);
            }
            org.setOrgLevel(level);
            org.setParentId((orgTree.getParentId() == null || "0.0".equals(orgTree.getParentId())) ? "0" : orgTree.getParentId());
            if("TRUE".equals(orgTree.getpDeleted())) {
                org.setOrgStatus(Constant.COMMON_STATUS_DELETED);
            }else{
                org.setOrgStatus(Constant.COMMON_STATUS_NORMAL);
            }
            if ("本部".equals(orgTree.getOrgType())) {
                org.setOrgType(Constant.OrgType.ORGRANK_VIRTUAL.getValue());
            }else{
                org.setOrgType(Constant.OrgType.ORGRANK_PRACTICAL.getValue());
            }
            org.setOrdernum(0);
            org.setCreater(Constant.SUPER_ADMIN);
            org.setCreateTime(new Date(myDate));
            org.setType("0");
            switch (orgTree.getOrgType()){
                case "部门": {
                    org.setIsParent(Constant.COMMON_YES_OR_NO_NO);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_DEPT.getValue());
                    org.setBasicType(Constant.OrgBasicType.DEPT.getValue());
                    break;
                }
                case "公司": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.COMPANY.getValue());
                    break;
                }
                case "本部": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.DIRECT.getValue());
                    break;
                }
                case "分公司": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_DEPT.getValue());
                    org.setBasicType(Constant.OrgBasicType.BRANCH.getValue());
                    break;
                }
                case "事业部": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.BU.getValue());
                    break;
                }
                default: break;
            }
            return org;
        }).collect(Collectors.toList());
        List<Org> listByCode = basicDataOrgTreeMapper.selectForUpdateByCode(myDate).stream().map(orgTree -> {
            Org org = new Org();
            org.setId(orgTree.getId());
            org.setVersion(1);
            org.setOrgCode(orgTree.getSocialCreditCode());
            org.setOrgName(orgTree.getOrgName());
            org.setShortName(orgTree.getShortName());
            org.setTenantId(Constant.SUPER_ADMIN_TENANTID);
            int level = 0;
            try {
                level = Integer.parseInt(orgTree.getOrgLevel().replace("L", ""));
            } catch (NumberFormatException e) {
                log.error("机构级别转换错误" + orgTree, e);
            }
            org.setOrgLevel(level);
            org.setParentId((orgTree.getParentId() == null || "0.0".equals(orgTree.getParentId())) ? "0" : orgTree.getParentId());
            if("TRUE".equals(orgTree.getpDeleted())) {
                org.setOrgStatus(Constant.COMMON_STATUS_DELETED);
            }else{
                org.setOrgStatus(Constant.COMMON_STATUS_NORMAL);
            }
            if ("本部".equals(orgTree.getOrgType())) {
                org.setOrgType(Constant.OrgType.ORGRANK_VIRTUAL.getValue());
            }else{
                org.setOrgType(Constant.OrgType.ORGRANK_PRACTICAL.getValue());
            }
            org.setOrdernum(0);
            org.setCreater(Constant.SUPER_ADMIN);
            org.setCreateTime(new Date(myDate));
            org.setType("0");
            switch (orgTree.getOrgType()){
                case "部门": {
                    org.setIsParent(Constant.COMMON_YES_OR_NO_NO);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_DEPT.getValue());
                    org.setBasicType(Constant.OrgBasicType.DEPT.getValue());
                    break;
                }
                case "公司": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.COMPANY.getValue());
                    break;
                }
                case "本部": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.DIRECT.getValue());
                    break;
                }
                case "分公司": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_DEPT.getValue());
                    org.setBasicType(Constant.OrgBasicType.BRANCH.getValue());
                    break;
                }
                case "事业部": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.BU.getValue());
                    break;
                }
                default: break;
            }
            return org;
        }).collect(Collectors.toList());
        List<Org> listById = basicDataOrgTreeMapper.selectForUpdateById(myDate).stream().map(orgTree -> {
            Org org = new Org();
            //修改
            org.setId(orgTree.getId());
            org.setVersion(1);
            org.setOrgCode(orgTree.getSocialCreditCode());
            org.setOrgName(orgTree.getOrgName());
            org.setShortName(orgTree.getShortName());
            int level = 0;
            try {
                level = Integer.parseInt(orgTree.getOrgLevel().replace("L", ""));
            } catch (NumberFormatException e) {
                log.error("机构级别转换错误" + orgTree, e);
            }
            org.setOrgLevel(level);
            org.setParentId((orgTree.getParentId() == null || "0.0".equals(orgTree.getParentId())) ? "0" : orgTree.getParentId());
            if("true".equals(orgTree.getpDeleted())) {
                org.setOrgStatus(Constant.COMMON_STATUS_DELETED);
            }else{
                org.setOrgStatus(Constant.COMMON_STATUS_NORMAL);
            }
            if ("本部".equals(orgTree.getOrgType())) {
                org.setOrgType(Constant.OrgType.ORGRANK_VIRTUAL.getValue());
            }else{
                org.setOrgType(Constant.OrgType.ORGRANK_PRACTICAL.getValue());
            }
            org.setOrdernum(0);
            org.setModUser(Constant.SUPER_ADMIN);
            org.setModTime(new Date(myDate));
            org.setType("0");
            switch (orgTree.getOrgType()){
                case "部门": {
                    org.setIsParent(Constant.COMMON_YES_OR_NO_NO);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_DEPT.getValue());
                    org.setBasicType(Constant.OrgBasicType.DEPT.getValue());
                    break;
                }
                case "公司": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.COMPANY.getValue());
                    break;
                }
                case "本部": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.DIRECT.getValue());
                    break;
                }
                case "分公司": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_DEPT.getValue());
                    org.setBasicType(Constant.OrgBasicType.BRANCH.getValue());
                    break;
                }
                case "事业部": {
                    //企业
                    org.setIsParent(Constant.COMMON_YES_OR_NO_YES);
                    org.setOrgRank(Constant.OrgRank.ORGRANK_COMPANY.getValue());
                    org.setBasicType(Constant.OrgBasicType.BU.getValue());
                    break;
                }
                default: break;
            }
            return org;
        }).collect(Collectors.toList());
        for(Org org : listAdd){
            try{
                orgService.addOrgOnly(org, user);
            }catch(Exception e){
                log.error(e.getMessage(), e);
            }
            count++;
            if(count % 500 == 0 || count == list.size()){
                log.info("已处理{}/{}条数据", count, list.size());
            }
        };
        for(Org org : listByCode){
            try{
                orgService.updateOrgByCode(org, user);
            }catch(Exception e){
                log.error(e.getMessage(), e);
            }
            count++;
            if(count % 500 == 0 || count == list.size()){
                log.info("已处理{}/{}条数据", count, list.size());
            }
        }
        for(Org org : listById){
            try{
                orgService.updateOrgOnly(org, user);
            }catch(Exception e){
                log.error(e.getMessage(), e);
            }
            count++;
            if(count % 500 == 0 || count == list.size()){
                log.info("已处理{}/{}条数据", count, list.size());
            }
        }
        log.info("共处理{}条数机构数据", list.size());
    }

    /**
     * 清理同步的机构历史数据,删除3个月之前的数据
     */
    @Override
    public void clearBasicDataOrg() {
        BasicDataOrgTreeExample example = new BasicDataOrgTreeExample();
        BasicDataOrgTreeExample.Criteria criteria = example.createCriteria();
        Calendar ca = Calendar.getInstance();
        ca.add(Calendar.MONTH, -3);
        criteria.andMyTimeLessThan(ca.getTimeInMillis());
        basicDataOrgTreeMapper.deleteByExample(example);
    }

    /**
     * 随机数
     * @return 随机数
     */
    private String getRandomStr() {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        int len = str.length();
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(str.charAt(random.nextInt(len)));
        }
        return sb.toString();
    }

    /**
     * SHA1 加密
     * @param str 待加密串
     * @return 加密后串
     */
    private String sha1Encrypt(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));
            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            log.error("创建加密方法失败", e);
            throw new BusinessException("创建加密方法失败");
        }
    }
}
